import { login, logout, createDynamicRoute } from '@/api/user'
import { getToken, setToken, removeToken, setRouteTable } from '@/utils/auth'
import router, { resetRouter } from '@/router'
import { jwtDecode } from 'jwt-decode'

const state = {
  // 用户token
  token: getToken(),
  // 用户id
  id: -1,
  // 用户名
  name: '',
  // 用户工号
  code: '',
  // 租户id
  tenantId: -1,
  // 组织机构id
  orgId: -1,
  // 角色列表
  roleList: [],
  // 公司id
  companyId: -1,
  // 登录错误次数
  loginAttempts: 0,
  // 是否锁定
  isLocked: false,
  // 被锁定的时间
  lockedTime: 0,
  // 解锁时间
  remainingTime: 0
}

const mutations = {
  /**
   * 设置用户token
   * @param {访客} state
   * @param {用户token} token
   */
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  /**
   * 设置用户id
   * @param {访客} state
   * @param {用户id} id
   */
  SET_ID: (state, id) => {
    state.id = id
  },
  /**
   * 设置用户名
   * @param {访客} state
   * @param {用户名} name
   */
  SET_NAME: (state, name) => {
    state.name = name
  },
  /**
   * 设置用户工号
   * @param {访客} state
   * @param {用户工号} code
   */
  SET_CODE: (state, code) => {
    state.code = code
  },
  /**
   * 设置租户id
   * @param {访客} state
   * @param {租户id} tenantId
   */
  SET_TENANT_ID: (state, tenantId) => {
    state.tenantId = tenantId
  },
  /**
   * 设置组织机构id
   * @param {访客} state
   * @param {组织机构id} orgId
   */
  SET_ORG_ID: (state, orgId) => {
    state.orgId = orgId
  },
  /**
   * 设置角色列表
   * @param {访客} state
   * @param {角色列表} roleList
   */
  SET_ROLE_LIST: (state, roleList) => {
    state.roleList = roleList
  },
  /**
   * 设置公司id
   * @param {访客} state
   * @param {公司id} companyId
   */
  SET_COMPANY_ID: (state, companyId) => {
    state.companyId = companyId
  },
  /**
   * 用户尝试登录的失败次数
   * @param {访客} state
   */
  incrementLoginAttempts(state) {
    state.loginAttempts += 1
  },
  /**
   * 重置用户登录失败次数
   * @param {用户状态} state
   */
  resetLoginAttempts(state) {
    state.loginAttempts = 0
  },
  /**
   * 锁定用户
   * @param {访客} state
   */
  lockLogin(state) {
    state.isLocked = true
    // 设置解锁定时器，在5分钟后解锁
    state.lockedTime = new Date()
    state.lockedTime.setMinutes(state.lockedTime.getMinutes() + 5)
    state.unlockTimer = setTimeout(() => {
      state.isLocked = false
      state.unlockTimer = null
    }, 5 * 60 * 1000) // 5分钟，单位为毫秒
  },
  /**
   * 解锁用户
   * @param {访客} state
   */
  unlockLogin(state) {
    state.isLocked = false
    // 清除解锁定时器
    clearTimeout(state.unlockTimer)
    state.unlockTimer = null
  },
  /**
   * 计算解锁还需多长时间，并返回
   * @param {访客} state
   * @returns {string} 解锁还需多长时间
   */
  getRemainingUnlockTime(state) {
    if (state.isLocked) {
      const remainingTime = state.lockedTime - Date.now()
      const minutes = Math.floor(remainingTime / (1000 * 60))
      const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000)
      state.remainingTime = `${minutes} 分钟 ${seconds} 秒`
    }
  },
  /**
   * 解析token信息并赋予用户属性
   * @param {访客} state
   */
  decodeToken(state, token) {
    const tokenObj = jwtDecode(token)
    state.id = tokenObj.token.id
    state.name = tokenObj.token.name
    state.code = tokenObj.token.code
    state.tenantId = tokenObj.token.tenantId
    state.orgId = tokenObj.token.orgId
    state.roleList = tokenObj.token.roleList
    state.companyId = tokenObj.token.companyId
  }
}

const actions = {
  // 用户登录
  login({ commit }, loginQuery) {
    return new Promise((resolve, reject) => {
      // 用户当前是被锁定的状态，则不允许登录
      if (state.isLocked) {
        commit('getRemainingUnlockTime')
        reject('登录已被锁定，请稍后再试。解锁时间：' + state.remainingTime)
      } else {
        // 尝试发起登录请求
        setTimeout(() => {
          // 判断用户是否被锁定
          if (state.loginAttempts >= 3) {
            commit('lockLogin')
            reject('登录已被锁定，稍后再试')
          } else {
            // 尝试登录
            login(loginQuery).then(response => {
              commit('SET_TOKEN', response)
              setToken(response)
              resolve('登录成功')
            }).catch(error => {
              reject(error)
            })
          }
        }, 1000)
      }
    })
  },

  /**
   * 获取路由表
   */
  getRouteTable({ commit }) {
    return new Promise((resolve, reject) => {
      createDynamicRoute().then(response => {
        commit('SET_ROLE_LIST', response.routeTable)
        setRouteTable(response.routeTable)
        resolve(response.routeTable)
      }).catch(error => {
        reject(error)
      })
    })
  },

  // passGateway({ commit, state }){
  //   return new Promise((resolve, reject) => {
  //     createDynamicRoute().then(response => {
  //       commit('SET_ROLE_LIST', response.routeTable)
  //       resolve(response.routeTable)
  //     }).catch(error => {
  //       reject(error)
  //     })
  //   })
  // },

  // user logout
  logout({ commit, state, dispatch }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        commit('SET_TOKEN', '')
        commit('SET_ROLE_LIST', [])
        removeToken()
        resetRouter()

        // reset visited views and cached views
        // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
        dispatch('tagsView/delAllViews', null, { root: true })

        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // remove token
  resetToken({ commit }) {
    return new Promise(resolve => {
      commit('SET_TOKEN', '')
      commit('SET_ROLE_LIST', [])
      removeToken()
      resolve()
    })
  },

  // dynamically modify permissions
  async changeRoles({ commit, dispatch }, role) {
    const token = role + '-token'

    commit('SET_TOKEN', token)
    setToken(token)

    const { roles } = await dispatch('getRouteTable')

    resetRouter()

    // generate accessible routes map based on roles
    const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
    // dynamically add accessible routes
    router.addRoutes(accessRoutes)

    // reset visited views and cached views
    dispatch('tagsView/delAllViews', null, { root: true })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
